// Package pay_api provides payment channel management functionality.
package pay_api

import (
	"context"

	"github.com/gogf/gf/v2/frame/g"
)

// ChannelService provides payment channel management operations
type ChannelService struct {
	client ClientInterface
}

// NewChannelService creates a new channel service instance
func NewChannelService(client ClientInterface) *ChannelService {
	return &ChannelService{
		client: client,
	}
}

// CreatePayChannel creates a new payment channel
func (s *ChannelService) CreatePayChannel(ctx context.Context, secret Secret, channelInfo PayChannelInfo) (*PayChannelInfo, error) {
	if err := s.validatePayChannelInfo(channelInfo); err != nil {
		return nil, err
	}

	reqData := g.Map{
		"payChannelInfo": channelInfo.Map(),
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", PayChannelCreateEndpoint, reqData)
	if err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrAPIError, "创建支付渠道失败", err.Error())
	}

	var result PayChannelAdminResponse
	if err := resp.Scan(&result); err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return nil, NewPayAPIError(ErrAPIError, result.Message)
	}

	return result.PayChannelInfo, nil
}

// UpdatePayChannel updates an existing payment channel
func (s *ChannelService) UpdatePayChannel(ctx context.Context, secret Secret, channelInfo PayChannelInfo) error {
	if err := s.validatePayChannelInfo(channelInfo); err != nil {
		return err
	}

	reqData := g.Map{
		"payChannelInfo": channelInfo.Map(),
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", PayChannelUpdateEndpoint, reqData)
	if err != nil {
		return NewPayAPIErrorWithDetails(ErrAPIError, "更新支付渠道失败", err.Error())
	}

	var result CommonRes[interface{}]
	if err := resp.Scan(&result); err != nil {
		return NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return NewPayAPIError(ErrAPIError, result.Message)
	}

	return nil
}

// GetPayChannel retrieves payment channel information
func (s *ChannelService) GetPayChannel(ctx context.Context, secret Secret, agentId, channelType int) (*PayChannelInfo, error) {
	if agentId <= 0 {
		return nil, NewPayAPIError(ErrInvalidRequest, "代理商ID不能为空")
	}
	if channelType <= 0 {
		return nil, NewPayAPIError(ErrInvalidRequest, "渠道类型不能为空")
	}

	reqData := g.Map{
		"agentId": agentId,
		"type":    channelType,
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", PayChannelGetEndpoint, reqData)
	if err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrAPIError, "获取支付渠道信息失败", err.Error())
	}

	var result PayChannelAdminResponse
	if err := resp.Scan(&result); err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return nil, NewPayAPIError(ErrAPIError, result.Message)
	}

	return result.PayChannelInfo, nil
}

// DeletePayChannel deletes a payment channel
func (s *ChannelService) DeletePayChannel(ctx context.Context, secret Secret, agentId, channelType int) error {
	if agentId <= 0 {
		return NewPayAPIError(ErrInvalidRequest, "代理商ID不能为空")
	}
	if channelType <= 0 {
		return NewPayAPIError(ErrInvalidRequest, "渠道类型不能为空")
	}

	reqData := g.Map{
		"agentId": agentId,
		"type":    channelType,
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", PayChannelDeleteEndpoint, reqData)
	if err != nil {
		return NewPayAPIErrorWithDetails(ErrAPIError, "删除支付渠道失败", err.Error())
	}

	var result CommonRes[interface{}]
	if err := resp.Scan(&result); err != nil {
		return NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return NewPayAPIError(ErrAPIError, result.Message)
	}

	return nil
}

// Helper methods
func (s *ChannelService) validatePayChannelInfo(channelInfo PayChannelInfo) error {
	if channelInfo.AgentId <= 0 {
		return NewPayAPIError(ErrInvalidRequest, "代理商ID不能为空")
	}
	if channelInfo.Type <= 0 {
		return NewPayAPIError(ErrInvalidRequest, "渠道类型不能为空")
	}
	if channelInfo.Name == "" {
		return NewPayAPIError(ErrInvalidRequest, "渠道名称不能为空")
	}
	return nil
}

// Legacy functions for backward compatibility
// These functions maintain the original API while using the new service internally

// PayChannelAdminCreate creates a new payment channel (legacy function)
func PayChannelAdminCreate(ctx context.Context, input *PayChannelAdminCreateInput) (*PayChannelInfo, error) {
	client, err := NewClient(&Config{
		BaseURL:  input.Baseurl,
		Username: input.Username,
		Key:      input.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return nil, err
	}

	service := NewChannelService(client)
	return service.CreatePayChannel(ctx, input.Secret, input.PayChannelInfo)
}

// PayChannelAdminUpdate updates an existing payment channel (legacy function)
func PayChannelAdminUpdate(ctx context.Context, input *PayChannelAdminUpdateInput) error {
	client, err := NewClient(&Config{
		BaseURL:  input.Baseurl,
		Username: input.Username,
		Key:      input.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return err
	}

	service := NewChannelService(client)
	return service.UpdatePayChannel(ctx, input.Secret, input.PayChannelInfo)
}

// PayChannelAdminGet retrieves payment channel information (legacy function)
func PayChannelAdminGet(ctx context.Context, input *PayChannelAdminDGInput) (*PayChannelInfo, error) {
	client, err := NewClient(&Config{
		BaseURL:  input.Baseurl,
		Username: input.Username,
		Key:      input.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return nil, err
	}

	service := NewChannelService(client)
	return service.GetPayChannel(ctx, input.Secret, input.AgentId, input.Type)
}

// PayChannelAdminDelete deletes a payment channel (legacy function)
func PayChannelAdminDelete(ctx context.Context, input *PayChannelAdminDGInput) error {
	client, err := NewClient(&Config{
		BaseURL:  input.Baseurl,
		Username: input.Username,
		Key:      input.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return err
	}

	service := NewChannelService(client)
	return service.DeletePayChannel(ctx, input.Secret, input.AgentId, input.Type)
}